import {StartRequest, Params, Method} from "../../types";

export enum RequestMethod {
  GET = 'get',
  POST = 'post',
  PUT = 'put',
  HEAD = 'head',
  DELETE = 'delete',
  OPTIONS = 'options',
  PATCH = 'patch',
  PURGE = 'purge',
  LINK = 'link',
  UNLINK = 'unlink'
}
let mStartRequest: StartRequest | undefined = undefined
const addStartRequestHandler = (startRequest: StartRequest) => {
  if (startRequest && typeof startRequest === 'function') {
    mStartRequest = startRequest
  }
}
function getCommonRequest<T>(
  url: string,
  method: Method,
  data?: Params,
  params?: Params,
  headers?: Params
): Promise<T> {
  if (mStartRequest) {
    return mStartRequest(
      url,
      method,
      data ? data : {},
      params ? params : {},
      headers ? headers : {}
    )
  } else {
    return Promise.reject('HttpClient is undefined')
  }
}

/**
 * 网络请求统一适配器
 */
export class HttpServicesAdapter {
  private readonly baseUrl: string | undefined

  constructor(baseUrl?: string) {
    this.baseUrl = baseUrl
  }

  /**
   *
   * @param url 请求地址
   * @param method 请求方式
   * @param data  请求参数(放在请求体中的参数)
   * @param params 请求参数(拼接在地址上的参数)
   * @param header 请求头
   */
  request<T>(
    url: string,
    method: Method,
    data?: Params,
    params?: Params,
    header?: Params
  ): Promise<T> {
    const requestUrl = this.baseUrl ? `${this.baseUrl}${url}` : url
    return getCommonRequest<T>(requestUrl, method, data, params, header)
  }

  /**
   *
   * @param url 请求地址
   * @param data  请求参数(放在请求体中的参数)
   * @param params 请求参数(拼接在地址上的参数)
   * @param header 请求头
   */
  get<T>(
    url: string,
    data?: Params,
    params?: Params,
    header?: Params
  ): Promise<T> {
    return this.request<T>(url, RequestMethod.GET, data, params, header)
  }

  /**
   *
   * @param url 请求地址
   * @param data  请求参数(放在请求体中的参数)
   * @param params 请求参数(拼接在地址上的参数)
   * @param header 请求头
   */
  post<T>(
    url: string,
    data?: Params,
    params?: Params,
    header?: Params
  ): Promise<T> {
    return this.request<T>(url, RequestMethod.POST, data, params, header)
  }

  /**
   *
   * @param url 请求地址
   * @param data  请求参数(放在请求体中的参数)
   * @param params 请求参数(拼接在地址上的参数)
   * @param header 请求头
   */
  put<T>(
    url: string,
    data?: Params,
    params?: Params,
    header?: Params
  ): Promise<T> {
    return this.request<T>(url, RequestMethod.PUT, data, params, header)
  }

  /**
   *
   * @param url 请求地址
   * @param data  请求参数(放在请求体中的参数)
   * @param params 请求参数(拼接在地址上的参数)
   * @param header 请求头
   */
  head<T>(
    url: string,
    data?: Params,
    params?: Params,
    header?: Params
  ): Promise<T> {
    return this.request<T>(url, RequestMethod.HEAD, data, params, header)
  }

  /**
   *
   * @param url 请求地址
   * @param data  请求参数(放在请求体中的参数)
   * @param params 请求参数(拼接在地址上的参数)
   * @param header 请求头
   */
  delete<T>(
    url: string,
    data?: Params,
    params?: Params,
    header?: Params
  ): Promise<T> {
    return this.request<T>(url, RequestMethod.DELETE, data, params, header)
  }

  /**
   *
   * @param url 请求地址
   * @param data  请求参数(放在请求体中的参数)
   * @param params 请求参数(拼接在地址上的参数)
   * @param header 请求头
   */
  options<T>(
    url: string,
    data?: Params,
    params?: Params,
    header?: Params
  ): Promise<T> {
    return this.request<T>(url, RequestMethod.OPTIONS, data, params, header)
  }

  /**
   *
   * @param url 请求地址
   * @param data  请求参数(放在请求体中的参数)
   * @param params 请求参数(拼接在地址上的参数)
   * @param header 请求头
   */
  purge<T>(
    url: string,
    data?: Params,
    params?: Params,
    header?: Params
  ): Promise<T> {
    return this.request<T>(url, RequestMethod.PURGE, data, params, header)
  }

  /**
   *
   * @param url 请求地址
   * @param data  请求参数(放在请求体中的参数)
   * @param params 请求参数(拼接在地址上的参数)
   * @param header 请求头
   */
  link<T>(
    url: string,
    data?: Params,
    params?: Params,
    header?: Params
  ): Promise<T> {
    return this.request<T>(url, RequestMethod.LINK, data, params, header)
  }

  /**
   *
   * @param url 请求地址
   * @param data  请求参数(放在请求体中的参数)
   * @param params 请求参数(拼接在地址上的参数)
   * @param header 请求头
   */
  unlink<T>(
    url: string,
    data?: Params,
    params?: Params,
    header?: Params
  ): Promise<T> {
    return this.request<T>(url, RequestMethod.UNLINK, data, params, header)
  }

  /**
   *
   * @param url 请求地址
   * @param data  请求参数(放在请求体中的参数)
   * @param params 请求参数(拼接在地址上的参数)
   * @param header 请求头
   */
  patch<T>(
    url: string,
    data?: Params,
    params?: Params,
    header?: Params
  ): Promise<T> {
    return this.request<T>(url, RequestMethod.PATCH, data, params, header)
  }

  /**
   * 基于端口地址创建适配器
   * @param baseUrl
   */
  static createHttpServicesAdapter(baseUrl?: string): HttpServicesAdapter {
    return new HttpServicesAdapter(baseUrl)
  }
  /**
   * 添加请求处理函数(适配平台请求)
   * @param startRequest
   */
  static addStartRequestHandler(startRequest: StartRequest) {
    addStartRequestHandler(startRequest)
  }
}
